﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;

namespace IssueVision.Data.Web
{
    /// <summary>
    /// User class client-side extensions
    /// </summary>
    public partial class User
    {
        /// <summary>
        /// Returns each user in the format of "user (FirstName LastName)"
        /// </summary>
        public string DisplayName
        {
            get { return _name == null ? " " : _name + " (" + _firstName + " " + _lastName + ")"; }
        }

        /// <summary>
        /// Returns each user type in the format of "Admin" or "User"
        /// </summary>
        public string DisplayUserType
        {
            get
            {
                switch (UserType)
                {
                    case "A":
                        return IssueVisionServiceConstant.UserTypeAdmin;
                    case "U":
                        return IssueVisionServiceConstant.UserTypeUser;
                    default:
                        return string.Empty;
                }
            }
            set
            {
                if (value != null)
                {
                    if (value.Contains(IssueVisionServiceConstant.UserTypeAdmin))
                    {
                        // Admin User
                        UserType = "A";
                    }
                    else if (value.Contains(IssueVisionServiceConstant.UserTypeUser))
                    {
                        // Normal User
                        UserType = "U";
                    }
                    else
                        UserType = String.Empty;
                }
            }
        }

        /// <summary>
        /// Stores the new password the user entered in the MyProfile UI,
        /// even if it is invalid.  This way we can validate the new password
        /// confirmation adequately all the times
        /// </summary>
        public string ActualNewPassword { get; set; }

        [Display(Name = "NewPasswordConfirmationLabel", ResourceType = typeof(IssueVisionResources))]
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ErrorResources))]
        [CustomValidation(typeof(User), "CheckNewPasswordConfirmation")]
        public string NewPasswordConfirmation
        {
            get
            {
                return _newPasswordConfirmation;
            }

            set
            {
                ValidateProperty("NewPasswordConfirmation", value);
                _newPasswordConfirmation = value;
                RaisePropertyChanged("NewPasswordConfirmation");
            }
        }
        private string _newPasswordConfirmation;

        /// <summary>
        /// Stores the password answer the user entered in the MyProfile UI,
        /// even if it is invalid.  This way we can validate the password answer
        /// confirmation adequately all the times
        /// </summary>
        public string ActualPasswordAnswer { get; set; }

        [Display(Name = "PasswordAnswerConfirmationLabel", ResourceType = typeof(IssueVisionResources))]
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ErrorResources))]
        [CustomValidation(typeof(User), "CheckPasswordAnswerConfirmation")]
        public string PasswordAnswerConfirmation
        {
            get
            {
                return _passwordAnswerConfirmation;
            }

            set
            {
                ValidateProperty("PasswordAnswerConfirmation", value);
                _passwordAnswerConfirmation = value;
                RaisePropertyChanged("PasswordAnswerConfirmation");
            }
        }
        private string _passwordAnswerConfirmation;

        /// <summary>
        /// Custom validation of whether new password and confirm password match
        /// </summary>
        /// <param name="newPasswordConfirmation"></param>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        public static ValidationResult CheckNewPasswordConfirmation(string newPasswordConfirmation, ValidationContext validationContext)
        {
            var currentUser = (User)validationContext.ObjectInstance;

            if (!string.IsNullOrEmpty(currentUser.ActualNewPassword) &&
                !string.IsNullOrEmpty(newPasswordConfirmation) &&
                currentUser.ActualNewPassword != newPasswordConfirmation)
            {
                return new ValidationResult(ErrorResources.ValidationErrorPasswordConfirmationMismatch, new[] { "NewPasswordConfirmation" });
            }

            return ValidationResult.Success;
        }

        /// <summary>
        /// Custom validation of whether password answer and confirm password answer match
        /// </summary>
        /// <param name="passwordAnswerConfirmation"></param>
        /// <param name="validationContext"></param>
        /// <returns></returns>
        public static ValidationResult CheckPasswordAnswerConfirmation(string passwordAnswerConfirmation, ValidationContext validationContext)
        {
            var currentUser = (User)validationContext.ObjectInstance;

            if (!string.IsNullOrEmpty(currentUser.ActualPasswordAnswer) &&
                !string.IsNullOrEmpty(passwordAnswerConfirmation) &&
                currentUser.ActualPasswordAnswer != passwordAnswerConfirmation)
            {
                return new ValidationResult(ErrorResources.ValidationErrorPasswordAnswerConfirmationMismatch, new[] { "PasswordAnswerConfirmation" });
            }

            return ValidationResult.Success;
        }

        /// <summary>
        /// Try validate the specified property for User class
        /// </summary>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public bool TryValidateProperty(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentNullException("propertyName");
            }

            if (propertyName == "Name" || propertyName == "FirstName"
                || propertyName == "LastName" || propertyName == "Email"
                || propertyName == "Password" || propertyName == "NewPassword"
                || propertyName == "NewPasswordConfirmation" || propertyName == "PasswordQuestion"
                || propertyName == "PasswordAnswer" || propertyName == "PasswordAnswerConfirmation"
                || propertyName == "UserType")
            {
                var context = new ValidationContext(this, null, null) { MemberName = propertyName };

                var validationResults = new Collection<ValidationResult>();

                switch (propertyName)
                {
                    case "Name":
                        return Validator.TryValidateProperty(Name, context, validationResults);
                    case "FirstName":
                        return Validator.TryValidateProperty(FirstName, context, validationResults);
                    case "LastName":
                        return Validator.TryValidateProperty(LastName, context, validationResults);
                    case "Email":
                        return Validator.TryValidateProperty(Email, context, validationResults);
                    case "Password":
                        return Validator.TryValidateProperty(Password, context, validationResults);
                    case "NewPassword":
                        return Validator.TryValidateProperty(NewPassword, context, validationResults);
                    case "NewPasswordConfirmation":
                        return Validator.TryValidateProperty(NewPasswordConfirmation, context, validationResults);
                    case "PasswordQuestion":
                        return Validator.TryValidateProperty(PasswordQuestion, context, validationResults);
                    case "PasswordAnswer":
                        return Validator.TryValidateProperty(PasswordAnswer, context, validationResults);
                    case "PasswordAnswerConfirmation":
                        return Validator.TryValidateProperty(PasswordAnswerConfirmation, context, validationResults);
                    case "UserType":
                        return Validator.TryValidateProperty(UserType, context, validationResults);
                }
            }
            return false;
        }
    }
}